package com.eternal.data;

import android.annotation.SuppressLint;

import androidx.lifecycle.Observer;
import androidx.paging.PagedList;

import android.graphics.PixelFormat;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.TextView;

import com.alibaba.android.arouter.facade.annotation.Route;
import com.eternal.base.IConnectAction;
import com.eternal.base.concat.BluetoothEvent;
import com.eternal.base.concat.DeviceModel;
import com.eternal.base.concat.TmpHum;
import com.eternal.base.data.RepositoryInjection;
import com.eternal.base.global.ActivityEvent;
import com.eternal.base.global.BluetoothKey;
import com.eternal.base.global.ProgressEvent;
import com.eternal.base.router.RouterFragmentPath;
import com.eternal.data.databinding.FragmentDataBinding;
import com.eternal.data.ui.GraphAdapter;
import com.eternal.data.ui.GraphHumBarView;
import com.eternal.data.ui.GraphHumView;
import com.eternal.data.ui.GraphTmpBarView;
import com.eternal.data.ui.GraphTmpView;
import com.eternal.framework.binding.command.BindingAction;
import com.eternal.framework.bus.Messenger;
import com.eternal.framework.bus.RxBus;
import com.eternal.framework.component.BaseFragment;
import com.eternal.framework.utils.KLog;

import java.util.Calendar;

import io.reactivex.Completable;
import io.reactivex.CompletableEmitter;
import io.reactivex.CompletableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * @author Administrator
 */
@Route(path = RouterFragmentPath.Data.PAGE_DATA)
public class DataFragment extends BaseFragment<FragmentDataBinding, DataModel> implements GraphAdapter.TimeCallback, IConnectAction {
    private GraphAdapter adapter;
    private TextView startTime, endTime;
    private ImageView ivEnd;
    private Calendar calendar;
    private byte type, port, deviceType;
    private Disposable init;
    private Consumer<Boolean> consumer;
    private Consumer<ActivityEvent> consumer2;
    private GraphTmpView tempView;
    private GraphHumView humView;
    private GraphTmpBarView tempBar;
    private GraphHumBarView humBar;

    @Override
    public int initContentView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return R.layout.fragment_data;
    }

    @Override
    public void connected() {
        viewModel.onResume();
    }

    @Override
    public void disconnected() {
        viewModel.onPause();
    }

    @SuppressLint("CheckResult")
    @Override
    public void onHiddenChanged(boolean hidden) {
        if (hidden) {
            viewModel.onPause();
            if (init != null) {
                init.dispose();
                init = null;
            }
        } else if (!viewModel.isReady()) {
            initHistory();
        } else {
            viewModel.onResume();
        }
    }

    @Override
    public int initVariableId() {
        return BR.model;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        port = getActivity().getIntent().getByteExtra(ActivityEvent.DEVICE_PORT, (byte) 0x0);
        deviceType = getActivity().getIntent().getByteExtra(ActivityEvent.DEVICE_TYPE, (byte) 0x1);
        viewModel.init(RepositoryInjection.providerHistoryRepository(),
                getActivity().getIntent().getStringExtra(ActivityEvent.DEVICE_MAC), port
        );
        init(view);
    }

    private void init(View view) {
        calendar = Calendar.getInstance();
        adapter = new GraphAdapter();
        adapter.setTimeCallback(this);
        initView(view);
    }

    private void initHistory() {
        init = viewModel.initHistory(consumer, consumer2)
                .compose(this.<Boolean>bindToLifecycle())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) {
                        if (viewModel.isConnect()) {
                            RxBus.getDefault().post(new ProgressEvent(ProgressEvent.START));
                        }
                    }
                }).subscribe(consumer, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) {
                        throwable.printStackTrace();
                        KLog.e(throwable);
                    }
                });
    }

    @SuppressLint("CheckResult")
    private void initView(final View view) {
        byte temp = deviceType == BluetoothKey.DEVICE_TYPE_E && port == 0 ? -1 : port;

        humView = view.findViewById(R.id.graph_hum);
        humView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
        humView.setAdapter(adapter);
        humView.setPort(temp);

        tempView = view.findViewById(R.id.graph_tmp);
        tempView.setAdapter(adapter);
        tempView.setPort(temp);

        tempBar = view.findViewById(R.id.bar_tmp);
        tempBar.setAdapter(adapter);

        humBar = view.findViewById(R.id.bar_hum);
        humBar.setAdapter(adapter);
        consumer = new Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean) throws Exception {
                KLog.i("init history is end");
                RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
                tempView.setDegree(aBoolean);
                tempBar.setDegree(aBoolean);
                viewModel.history.observe(DataFragment.this, new Observer<PagedList<TmpHum>>() {
                    @Override
                    public void onChanged(@Nullable final PagedList<TmpHum> tmpHums) {
                        viewModel.isDegree().compose(DataFragment.this.<Boolean>bindToLifecycle())
                                .subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread())
                                .subscribe(new Consumer<Boolean>() {
                                    @Override
                                    public void accept(Boolean isDegree) throws Exception {
                                        tempView.setDegree(isDegree);
                                        try {
                                            tempView.hidePositionScroller(false);
                                            tempBar.hidePositionScroller(false);
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                            KLog.e(e);
                                        }
                                        tempBar.setDegree(isDegree);
                                        adapter.submitList(tmpHums);
                                    }
                                }, new Consumer<Throwable>() {
                                    @Override
                                    public void accept(Throwable throwable) {
                                        adapter.submitList(tmpHums);
                                        throwable.printStackTrace();
                                        KLog.e(throwable);
                                    }
                                });
                    }
                });
            }
        };
        //TODO
        consumer2 = new Consumer<ActivityEvent>() {
            @Override
            public void accept(ActivityEvent event) throws Exception {
                if (event.what == ActivityEvent.SET_DEVICE_MODEL_INFO_DEGREE) {
                    KLog.e("收到更改温度单位消息.0..............");
                    DeviceModel info = (DeviceModel) event.obj;
                    if (info != null) {
                        RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
                        setTempDegree(info.isDegree);
                    }
                }
            }
        };

        RadioGroup group = view.findViewById(R.id.radioGroup);
        group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                if (checkedId == R.id.radio_day) {
                    adapter.setDistance(86400);
                    type = 1;
                } else if (checkedId == R.id.radio_week) {
                    adapter.setDistance(604800);
                    type = 2;
                } else if (checkedId == R.id.radio_month) {
                    adapter.setDistance(2678400);
                    type = 3;
                } else if (checkedId == R.id.radio_year) {
                    adapter.setDistance(31536000);
                    type = 4;
                } else {
                    adapter.setDistance(3600);
                    type = 0;
                }
            }
        });
        group.check(R.id.radio_hour);

        startTime = view.findViewById(R.id.tv_start);
        endTime = view.findViewById(R.id.tv_end);
        ivEnd = view.findViewById(R.id.iv_end);
        View.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                changeTime(false);
            }
        };
        view.findViewById(R.id.tv_start).setOnClickListener(listener);
        view.findViewById(R.id.iv_start).setOnClickListener(listener);
        listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                changeTime(true);
            }
        };
        view.findViewById(R.id.tv_end).setOnClickListener(listener);
        view.findViewById(R.id.iv_end).setOnClickListener(listener);
    }

    private void setTempDegree(boolean isDegree) {
        tempView.setDegree(isDegree);
        tempBar.setDegree(isDegree);
        try {
            tempView.hidePositionScroller(false);
            tempBar.hidePositionScroller(false);
        } catch (Exception e) {
            e.printStackTrace();
            KLog.e(e);
        }

        viewModel.history.observe(DataFragment.this, new Observer<PagedList<TmpHum>>() {
            @Override
            public void onChanged(@Nullable PagedList<TmpHum> tmpHums) {
                adapter.submitList(tmpHums);
            }
        });

    }

    @Override
    public void onDestroyView() {
        if (init != null) {
            init.dispose();
            init = null;
        }
        super.onDestroyView();
    }

    @Override
    public void setStart(final String time) {
        Completable.create(new CompletableOnSubscribe() {
            @Override
            public void subscribe(CompletableEmitter emitter) throws Exception {
                startTime.setText(time.toUpperCase());
                emitter.onComplete();
            }
        }).compose(bindToLifecycle()).subscribeOn(AndroidSchedulers.mainThread()).subscribe();
    }

    @Override
    public void setEnd(final String time, final boolean isEnd) {
        Completable.create(new CompletableOnSubscribe() {
            @Override
            public void subscribe(CompletableEmitter emitter) throws Exception {
                boolean isEnd = adapter.isEnd();
                endTime.setText(time.toUpperCase());
                if (ivEnd.getVisibility() == View.VISIBLE && isEnd) {
                    ivEnd.setVisibility(View.GONE);
                } else if (ivEnd.getVisibility() == View.GONE && !isEnd) {
                    ivEnd.setVisibility(View.VISIBLE);
                }
                emitter.onComplete();
            }
        }).compose(bindToLifecycle()).subscribeOn(AndroidSchedulers.mainThread()).subscribe();
    }

    private void changeTime(boolean add) {
        KLog.e("change time");
        calendar.setTimeInMillis(adapter.getMinTime());
        if (add) {
            switch (type) {
                case 0:
                    calendar.add(Calendar.HOUR_OF_DAY, 1);
                    break;
                case 1:
                    calendar.add(Calendar.DAY_OF_MONTH, 1);
                    break;
                case 2:
                    calendar.add(Calendar.DAY_OF_MONTH, 7);
                    break;
                case 3:
                    calendar.add(Calendar.MONTH, 1);
                    break;
                default:
                    calendar.add(Calendar.YEAR, 1);
            }
        } else {
            switch (type) {
                case 0:
                    calendar.add(Calendar.HOUR_OF_DAY, -1);
                    break;
                case 1:
                    calendar.add(Calendar.DAY_OF_MONTH, -1);
                    break;
                case 2:
                    calendar.add(Calendar.DAY_OF_MONTH, -7);
                    break;
                case 3:
                    calendar.add(Calendar.MONTH, -1);
                    break;
                default:
                    calendar.add(Calendar.YEAR, -1);
            }
        }
        adapter.setMinTime(((int) (calendar.getTimeInMillis() / 1000)));
        tempView.setScrollerOpen(false);
        tempBar.setScrollerOpen(false);
        humView.setScrollerOpen(false);
        humBar.setScrollerOpen(false);

    }
}